// Ultimate3dRendererMain.cpp : Defines the entry point for the application.
//

#include "Ultimate3dRendererMain.h"


// Global Variables:
HINSTANCE g_hInst = NULL;
HWND g_hMainWindow = NULL;
RenderMan g_RenderMan;

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	std::ofstream ofs("ultimate3drenderer.log");
	std::clog.rdbuf(ofs.rdbuf());
	
	int iReturnValue = 0;

	// Format main window class
	WNDCLASSEX wce;
	memset(&wce, 0, sizeof(WNDCLASSEX));
	wce.cbSize = sizeof(WNDCLASSEX);
	wce.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
	wce.lpfnWndProc = (WNDPROC)MainWindowProc;
	wce.hInstance = hInstance;
	wce.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wce.hCursor = LoadCursor(NULL, IDC_ARROW);
	wce.lpszClassName = MAIN_WINDOW_CLASS_NAME;

	// Calculate main window position
	int iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	int x = (iScreenWidth - MAIN_WINDOW_WIDTH) / 2;
	int y = (iScreenHeight - MAIN_WINDOW_HEIGHT) / 2;

	srand((unsigned)time(NULL));
	
	// Register main window class
	if (RegisterClassEx(&wce) != 0)
	{
		// Save application instance
		g_hInst = hInstance;

		// Create main window
		g_hMainWindow = CreateWindowEx(0, MAIN_WINDOW_CLASS_NAME, NULL, WS_POPUP | WS_VISIBLE, x, y, 
			MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT, NULL, NULL, g_hInst, NULL);
		if (g_hMainWindow != NULL)
		{
			try
			{
				// Init
				Initialize();

				// Main
				MainLoop();

				// Shutdown
				Shutdown();
			}
			catch(std::exception &e)
			{
				std::clog << e.what() << std::endl;
			}
			catch(...)
			{
				std::clog << "Unknown exception! Exitting..." << std::endl;
			}
		}
		else
		{
			// Error creating main window
			MessageBox(NULL, _T("Failed to create the unbelievable Ultimate 3D Renderer main window!"), _T("Error..."), MB_OK | MB_ICONERROR);
			iReturnValue = -1;
		}

		// Unregister main window class
		UnregisterClass(MAIN_WINDOW_CLASS_NAME, hInstance);
	}
	else
	{
		// Error registering main window class
		MessageBox(NULL, _T("Failed to register the unbelievable Ultimate 3D Renderer main window!!"), _T("Error..."), MB_OK | MB_ICONERROR);
		iReturnValue = -1;
	}

	std::clog.rdbuf(std::cerr.rdbuf());
	return iReturnValue;
}

void Initialize() 
{
	g_RenderMan.Initialize(g_hMainWindow, MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT);
}

MSG MainLoop()
{
	MSG msg;

	while (true)
	{
		// Main message loop:
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);			
		}

		g_RenderMan.DrawFrame();
	}

	return msg;
}


void Shutdown()
{
	g_RenderMan.Shutdown();
}

LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	int lResult = 0;

	// Process main window messages
	switch (uMsg)
	{
		case WM_DESTROY:
			{
				// Exit application
				PostQuitMessage(0);
			}
			break;

		case WM_KEYDOWN:
			{
				if (wParam == VK_ESCAPE)
				{
					DestroyWindow(g_hMainWindow);
				}
			}
			break;
		default:
			{
				// Main window default procedure
				lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
			}
	}

	return lResult;
}